/*************************************************************************//**
 *****************************************************************************
 * @file   include/sys/fs.h
 * @brief  Header file for File System.
 * @author Forrest Yu
 * @date   2008
 *****************************************************************************
 *****************************************************************************/

#ifndef _ORANGES_FS_H_
#define _ORANGES_FS_H_

/**
 * @struct dev_drv_map fs.h "include/sys/fs.h"
 * @brief  The Device_nr.\ - Driver_nr.\ MAP.
 */
struct dev_drv_map {
    int driver_nr; /**< The proc nr.\ of the device driver. */
};

/**
 * @def   MAGIC_V1
 * @brief Magic number of FS v1.0
 */
#define MAGIC_V1    0x111

/**
 * @struct super_block fs.h "include/fs.h"
 * @brief  The 2nd sector of the FS
 *
 * Remember to change SUPER_BLOCK_SIZE if the members are changed.
 */
struct super_block {
    u32 magic;        /**< Magic number */
    u32 nr_inodes;    /**< How many inodes */
    u32 nr_sects;     /**< How many sectors */
    u32 nr_imap_sects;    /**< How many inode-map sectors */
    u32 nr_smap_sects;    /**< How many sector-map sectors */
    u32 n_1st_sect;   /**< Number of the 1st data sector */
    u32 nr_inode_sects;   /**< How many inode sectors */
    u32 root_inode;       /**< Inode nr of root directory */
    u32 inode_size;       /**< INODE_SIZE */
    u32 inode_isize_off;  /**< Offset of `struct inode::i_size' */
    u32 inode_start_off;  /**< Offset of `struct inode::i_start_sect' */
    u32 dir_ent_size;     /**< DIR_ENTRY_SIZE */
    u32 dir_ent_inode_off;/**< Offset of `struct dir_entry::inode_nr' */
    u32 dir_ent_fname_off;/**< Offset of `struct dir_entry::name' */

    /*
     * the following item(s) are only present in memory
     */
    int sb_dev;     /**< the super block's home device */
};

/**
 * @def   SUPER_BLOCK_SIZE
 * @brief The size of super block \b in \b the \b device.
 *
 * Note that this is the size of the struct in the device, \b NOT in memory.
 * The size in memory is larger because of some more members.
 */
#define SUPER_BLOCK_SIZE    56

/**
 * @struct inode
 * @brief  i-node
 *
 * The \c start_sect and\c nr_sects locate the file in the device,
 * and the size show how many bytes is used.
 * If <tt> size < (nr_sects * SECTOR_SIZE) </tt>, the rest bytes
 * are wasted and reserved for later writing.
 *
 * \b NOTE: Remember to change INODE_SIZE if the members are changed
 */

//固定分区
struct inode {
    u32 i_mode;     /**< Accsess mode */
    u32 i_size;     /**< File size */
    u32 i_start_sect;   /**< The first sector of the data */
    u32 i_nr_sects; /**< How many sectors the file occupies */
    u8  _unused[16];    /**< Stuff for alignment */

    /* the following items are only present in memory */
    int i_dev;
    int i_cnt;      /**< How many procs share this inode  */
    int i_num;      /**< inode nr.  */
};

/**
 * @def   INODE_SIZE
 * @brief The size of i-node stored \b in \b the \b device.
 *
 * Note that this is the size of the struct in the device, \b NOT in memory.
 * The size in memory is larger because of some more members.
 */
#define INODE_SIZE  32

/**
 * @def   MAX_FILENAME_LEN
 * @brief Max len of a filename
 * @see   dir_entry
 */
#define MAX_FILENAME_LEN  12

/**
 * @struct dir_entry
 * @brief  Directory Entry
 */
struct dir_entry {
    int   inode_nr;       /**< inode nr. */
    char  name[MAX_FILENAME_LEN]; /**< Filename */
    int   created_time;
    int   changed_time;
    char  pass[16];
};

/**
 * @def   DIR_ENTRY_SIZE
 * @brief The size of directory entry in the device.
 *
 * It is as same as the size in memory.
 */
#define DIR_ENTRY_SIZE  sizeof(struct dir_entry)

/**
 * @struct file_desc
 * @brief  File Descriptor
 */
struct file_desc {
    int     fd_mode;    /**< R or W */
    int     fd_pos;     /**< Current position for R/W. */
    struct inode*   fd_inode;   /**< Ptr to the i-node */
};


/**
 * Since all invocations of `rw_sector()' in FS look similar (most of the
 * params are the same), we use this macro to make code more readable.
 */
#define RD_SECT(dev,sect_nr) rw_sector(DEV_READ, \
                       dev,             \
                       (sect_nr) * SECTOR_SIZE,     \
                       SECTOR_SIZE, /* read one sector */ \
                       TASK_FS,             \
                       fsbuf);

#define WR_SECT(dev,sect_nr) rw_sector(DEV_WRITE, \
                       dev,             \
                       (sect_nr) * SECTOR_SIZE,     \
                       SECTOR_SIZE, /* write one sector */ \
                       TASK_FS,             \
                       fsbuf);


#endif /* _ORANGES_FS_H_ */
